/**
 * 
 */
package optimization.naturalOptimization.population.individual;

import optimization.naturalOptimization.population.Population;

/**
 * This class provides the superclass for a individual.
 * 
 * @author Kevin Wagner
 * @version 1.0
 * @param <T>
 *            type of search space
 * 
 */
public abstract class Individual<T> {

	private T position;
	private double positionFitness;
	private Population parentPopulation;

	/**
	 * Creates a new individual for the given population.
	 * 
	 * @param parentPopulation
	 */
	public Individual(Population parentPopulation) {
		this.parentPopulation = parentPopulation;
	}

	/**
	 * Sets the position for the individual.
	 * 
	 * @param position
	 *            new position
	 */
	public void setPosition(T position) {
		this.position = position;
	}

	/**
	 * Returns the position of the individual.
	 * 
	 * @return position
	 */
	public T getPosition() {
		return position;
	}

	/**
	 * Returns the population of this individual.
	 * 
	 * @return the population that manages this individual.
	 */
	public Population getParentPopulation() {
		return parentPopulation;
	}

	/**
	 * Sets the parent Population for this individual.
	 * 
	 * @param parentPopulation
	 *            new parent population
	 */
	public void setParentPopulation(Population parentPopulation) {
		this.parentPopulation = parentPopulation;
	}

	/**
	 * Performs a optimization step for this individual.
	 */
	public abstract void performStep();

	/**
	 * Returns the fitness value of the position.
	 * 
	 * @return the fitness value
	 */
	public double getPositionFitness() {
		return positionFitness;
	}

	/**
	 * @param positionFitness
	 *            the positionFitness to set
	 */
	public void setPositionFitness(double positionFitness) {
		this.positionFitness = positionFitness;
	}
	
	/**
	 * Checks the position for feasibility.
	 * @return feasibility of position
	 */
	@SuppressWarnings("unchecked")
	public boolean isFeasiblePosition(){
		return getParentPopulation().getParentOptimization().getSearchSpace().isFeasible(position);
	}
}
